/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "crc.h"
#include "dma.h"
#include "rtc.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/*                                             包含文件
*********************************************************************************************************
*/

#include <includes.h>
#include "stm32f1xx_hal.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/*
*********************************************************************************************************
*                                               宏定义
*********************************************************************************************************
*/

#define START_TASK_PRIO		3


#define LED0_TASK_PRIO		4
#define LED1_TASK_PRIO		5

/* 任务堆栈大小	*/
//任务堆大小过大会报错，可以试着改小一点
#define START_STK_SIZE 		128u

#define LED0_STK_SIZE 		64u
#define LED1_STK_SIZE 		64u

/* 任务栈 */	
__align(8) static  CPU_STK  AppTaskStartStk[APP_TASK_START_STK_SIZE];

__align(8) static  CPU_STK  AppTaskKeyScanStk[APP_TASK_KEY_SCAN_STK_SIZE];
__align(8) static  CPU_STK  AppTaskDesktopStk[APP_TASK_DESKTOP_STK_SIZE];

__align(8) static  CPU_STK LED0_TASK_STK[LED0_STK_SIZE];
__align(8) static  CPU_STK LED1_TASK_STK[LED1_STK_SIZE];

/* 任务控制块 */
static  OS_TCB   AppTaskStartTCB;
static  OS_TCB   AppTaskKeyScanTCB;

static  OS_TCB   AppTaskDesktopTCB;

static  OS_TCB Led0TaskTCB;
static  OS_TCB Led1TaskTCB;
/* USER CODE END PTD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */


/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_NVIC_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_NVIC_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/*
*********************************************************************************************************
*                                             函数声明
*********************************************************************************************************
*/

static  void  AppTaskStart  (void *p_arg);
static  void  BSPTaskCreate (void);
static  void  AppTaskCreate(void);

static  void  led_pc2(void *p_arg);
static  void  led_pc3(void *p_arg);

//extern void TOUCH_Calibrate(void);



/*
*********************************************************************************************************
*                                            
*********************************************************************************************************
*/
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
    OS_ERR  os_err;

    OSInit(&os_err);                                               		/* 初始化 uC/OS-III.                                      */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  MX_SPI2_Init();
  MX_USART1_UART_Init();
  MX_RTC_Init();
  MX_TIM5_Init();
  MX_UART5_Init();
  MX_CRC_Init();

  /* Initialize interrupts */
  MX_NVIC_Init();
  /* USER CODE BEGIN 2 */
  /* YangJie add 2021.05.20*/
  /* Initialize BSP functions */
  CPU_Init();	//初始化CPU

  BSP_Init();  //初始化BSP  	
		
  //BSP_Tick_Init();//初始化systick
  Mem_Init(); 	//初始化存储管理器 
	
  //创建启动任务
  OSTaskCreate((OS_TCB     *)&AppTaskStartTCB,                // 任务TCB                               
                 (CPU_CHAR   *)"App Task Start", 								// 任务名称                             
                 (OS_TASK_PTR ) AppTaskStart,									  // 任务函数指针                                
                 (void       *) 0,																	// 可选输入数据
                 (OS_PRIO     ) APP_TASK_START_PRIO,							// 优先级
                 (CPU_STK    *)&AppTaskStartStk[0],							// 任务栈基地址
                 (CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,		// 栈“水印”限制
                 (CPU_STK_SIZE) APP_TASK_START_STK_SIZE,        //栈大小
                 (OS_MSG_QTY  ) 5u,
                 (OS_TICK     ) 0u,
                 (void       *) 0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),//可选配置
                 (OS_ERR     *)&os_err);															//错误代码

  //检查错误
  if(os_err!=OS_ERR_NONE)  bsp_result|=BSP_OS;

  //开始执行任务，从此处开始由ucos系统调度
    OSStart(&os_err);  

  //检查错误，正常的程序已由ucos调度，不应运行到此处
  if(os_err!=OS_ERR_NONE)  bsp_result|=BSP_OS;
		
  BSP_TRACE_INFO(("OS err:0x%x",bsp_result));    
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV128;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief NVIC Configuration.
  * @retval None
  */
static void MX_NVIC_Init(void)
{
  /* RTC_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(RTC_IRQn, 1, 0);
  HAL_NVIC_EnableIRQ(RTC_IRQn);
  /* DMA1_Channel3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 3, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
  /* USART1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(USART1_IRQn);
  /* TIM5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(TIM5_IRQn, 3, 0);
  HAL_NVIC_EnableIRQ(TIM5_IRQn);
  /* UART5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(UART5_IRQn, 6, 0);
  HAL_NVIC_EnableIRQ(UART5_IRQn);
}

/* USER CODE BEGIN 4 */
/**************************************************************************************/

/**
  * @brief  启动任务函数，主要完成ucos、BSP、GUI以及其它任务的初始化
  * @param  p_arg: OSTaskCreate创建时传入的数据指针
  * @retval 无
  */
static  void  AppTaskStart (void *p_arg)
{
    OS_ERR      os_err;

   (void)p_arg;                              

#if OS_CFG_STAT_TASK_EN > 0u
    OSStatTaskCPUUsageInit(&os_err); //计算无任务时CPU使用率                            
#endif

#ifdef CPU_CFG_INT_DIS_MEAS_EN
    CPU_IntDisMeasMaxCurReset();
#endif


	//APP_TRACE_DBG(("\r\n正在创建驱动、应用任务..."));

	//创建驱动任务
	BSPTaskCreate();
	
	OSTimeDly(500u, 
						OS_OPT_TIME_DLY,
						&os_err);
						
	//创建应用任务
	AppTaskCreate();  

	//检查硬件错误
	// Hardware_Error_Check();
	
 //任务死循环
	while (DEF_TRUE) 
	{                                        
    // LED2_TOGGLE ;
		//APP_TRACE_DBG(("cpu使用率:%.2f%%\n",((float)OSStatTaskCPUUsage/100)));

  	//延时，所有任务函数的死循环内都应有至少1ms延时
		 //特别是高优先级的任务，若无延时，其它低优先级任务可能会无机会执行
		OSTimeDly(1000u, 
									OS_OPT_TIME_DLY,
									&os_err);
	}	
		
}

/**
  * @brief  按键任务函数
  * @param  无
  * @retval 无
  */
void  AppTaskKeyScan  (void )
{

	OS_ERR  os_err;
	
		  /* 创建事件标志组 flag_grp */
  OSFlagCreate ((OS_FLAG_GRP  *)&Key_Flag_Grp,        //指向事件标志组的指针
                (CPU_CHAR     *)"KEY Flag",  //事件标志组的名字
                (OS_FLAGS      )0,                //事件标志组的初始值
                (OS_ERR       *)&os_err);					  //返回错误类型


	while(1)
	{
			//GUI_TOUCH_Exec();
		
			if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON  )
			{
						OSFlagPost ((OS_FLAG_GRP  *)&Key_Flag_Grp,                             //将标志组的BIT0清0
													(OS_FLAGS      )EVEN_KEY1_DOWN,
													(OS_OPT        )OS_OPT_POST_FLAG_SET,
													(OS_ERR       *)&os_err);
		
				   
			}
			else
			{
			
			}
			
			if( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON  )
			{
						OSFlagPost ((OS_FLAG_GRP  *)&Key_Flag_Grp,                             //将标志组的BIT0清0
													(OS_FLAGS      )EVEN_KEY2_DOWN,
													(OS_OPT        )OS_OPT_POST_FLAG_SET,
													(OS_ERR       *)&os_err);
				    
			}
			else
			{
			
			}
			
			//延时，所有任务函数的死循环内都应有至少1ms延时
		  //特别是高优先级的任务，若无延时，其它低优先级任务可能会无机会执行
			OSTimeDly(10u, 
									OS_OPT_TIME_DLY,
									&os_err);

			
	}
}
	
	
/**
  * @brief  创建驱动任务，如按键，定时扫描等
  * @param  无
  * @retval 无
  */
static  void  BSPTaskCreate (void)
{
	OS_ERR  os_err;

		/* 创建LED0任务 */
	OSTaskCreate((OS_TCB 	* )&Led0TaskTCB,		
				 (CPU_CHAR	* )"led_pc2", 		
                 (OS_TASK_PTR )led_pc2, 			
                 (void		* )0,					
                 (OS_PRIO	  )LED0_TASK_PRIO,     
                 (CPU_STK   * )&LED0_TASK_STK[0],	
                 (CPU_STK_SIZE)LED0_STK_SIZE/10,	
                 (CPU_STK_SIZE)LED0_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&os_err);				
				 
	/* 创建LED1任务 */
	OSTaskCreate((OS_TCB 	* )&Led1TaskTCB,		
				 (CPU_CHAR	* )"led_pc3", 		
                 (OS_TASK_PTR )led_pc3, 			
                 (void		* )0,					
                 (OS_PRIO	  )LED1_TASK_PRIO,     
                 (CPU_STK   * )&LED1_TASK_STK[0],	
                 (CPU_STK_SIZE)LED1_STK_SIZE/10,	
                 (CPU_STK_SIZE)LED1_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&os_err);		
							 
		//创建扫描任务
	OSTaskCreate((OS_TCB     *)&AppTaskKeyScanTCB,             // 任务TCB                               
							 (CPU_CHAR   *)"Key Scan", 									// 任务名称                             
							 (OS_TASK_PTR ) AppTaskKeyScan,									  // 任务函数指针                                
							 (void       *) 0,																	// 可选输入数据
							 (OS_PRIO     ) APP_TASK_KEY_SCAN_PRIO,					// 优先级
							 (CPU_STK    *)&AppTaskKeyScanStk[0],							// 任务栈基地址
							 (CPU_STK_SIZE) APP_TASK_KEY_SCAN_STK_SIZE / 10,				// 栈“水印”限制
							 (CPU_STK_SIZE) APP_TASK_KEY_SCAN_STK_SIZE,        		//栈大小
							 (OS_MSG_QTY  ) 0u,
							 (OS_TICK     ) 0u,
							 (void       *) 0,
							 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),//可选配置
							 (OS_ERR     *)&os_err);															//错误代码
							 
	/*						 
	//创建电容触摸按键扫描任务
	OSTaskCreate((OS_TCB     *)&BSPTaskTouchPadScanTCB,             // 任务TCB                               
							 (CPU_CHAR   *)"Touch Pad", 									// 任务名称                             
							 (OS_TASK_PTR ) BSPTaskTouchPadScan,									  // 任务函数指针                                
							 (void       *) 0,																	// 可选输入数据
							 (OS_PRIO     ) BSP_TASK_TOUCHPAD_SCAN_PRIO,					// 优先级
							 (CPU_STK    *)&BSPTaskTouchPadScanStk[0],							// 任务栈基地址
							 (CPU_STK_SIZE) BSP_TASK_TOUCHPAD_SCAN_STK_SIZE / 10,				// 栈“水印”限制
							 (CPU_STK_SIZE) BSP_TASK_TOUCHPAD_SCAN_STK_SIZE,        		//栈大小
							 (OS_MSG_QTY  ) 0u,
							 (OS_TICK     ) 0u,
							 (void       *) 0,
							 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),//可选配置
							 (OS_ERR     *)&os_err);			

*/
}

/**
  * @brief  创建应用任务的函数，它会被启动任务调用以创建应用
  * @param  无
  * @retval 无
  */
static  void  AppTaskCreate (void)
{
	OS_ERR  os_err;

	//判断是否需要校准
	{
		//创建应用任务,桌面任务
		OSTaskCreate((OS_TCB     *)&AppTaskDesktopTCB,             // 任务TCB                               
								 (CPU_CHAR   *)"GUI Task", 									// 任务名称                             
								 (OS_TASK_PTR ) AppTaskDesktop,									  // 任务函数指针                                
								 (void       *) 0,																	// 可选输入数据
								 (OS_PRIO     ) APP_TASK_DESKTOP_PRIO,					// 优先级
								 (CPU_STK    *)&AppTaskDesktopStk[0],							// 任务栈基地址
								 (CPU_STK_SIZE) APP_TASK_DESKTOP_STK_SIZE / 10,				// 栈“水印”限制
								 (CPU_STK_SIZE) APP_TASK_DESKTOP_STK_SIZE,        		//栈大小
								 (OS_MSG_QTY  ) 0u,
								 (OS_TICK     ) 0u,
								 (void       *) 0,
								 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),//可选配置
								 (OS_ERR     *)&os_err);															//错误代码
	}
}

static  void  led_pc2 (void *p_arg)
{
  OS_ERR      os_err;

  while (DEF_TRUE)
  {
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET);
		OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_HMSM_STRICT, &os_err);
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET);
		OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_HMSM_STRICT, &os_err);
		OSTimeDly(10u, 
									OS_OPT_TIME_DLY,
									&os_err);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

static  void  led_pc3 (void *p_arg)
{
  OS_ERR      os_err;

  while (DEF_TRUE)
  {
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET);
		OSTimeDlyHMSM(0, 0, 0, 500, OS_OPT_TIME_HMSM_STRICT, &os_err);
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET);
		OSTimeDlyHMSM(0, 0, 0, 500, OS_OPT_TIME_HMSM_STRICT, &os_err);
		OSTimeDly(10u, 
									OS_OPT_TIME_DLY,
									&os_err);
  }
}

/**************************************************************************************/
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
